package com.example.producer;

import javax.swing.*;
import java.awt.*;
import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumer {

    private static final int BUFFER_SIZE = 10;
    private static final Queue<Integer> buffer = new LinkedList<>();
    private static final Object lock = new Object();
    private static boolean isProducing = false;
    private static boolean isConsuming = false;
    private static JProgressBar producerProgress;
    private static JProgressBar consumerProgress;

    public static void main(String[] args) {
        JFrame frame = new JFrame("生产者与消费者模拟");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 500); // 调整窗口大小以容纳进度条
        frame.setLayout(new BorderLayout());
        frame.getContentPane().setBackground(new Color(240, 240, 240));

        // 创建缓冲区面板
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, BUFFER_SIZE, 5, 5));
        panel.setBackground(new Color(240, 240, 240));
        JLabel[] labels = new JLabel[BUFFER_SIZE];
        for (int i = 0; i < BUFFER_SIZE; i++) {
            labels[i] = new JLabel("空", SwingConstants.CENTER);
            labels[i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
            labels[i].setBackground(Color.WHITE);
            labels[i].setOpaque(true);
            labels[i].setFont(new Font("微软雅黑", Font.BOLD, 14));
            panel.add(labels[i]);
        }

        // 状态面板
        JPanel statusPanel = new JPanel();
        statusPanel.setLayout(new GridLayout(1, 3, 20, 10));
        statusPanel.setBackground(new Color(240, 240, 240));

        // 生产者状态面板
        JPanel producerStatusPanel = new JPanel(new BorderLayout());
        JLabel producerStatus = new JLabel("生产者：停止", SwingConstants.CENTER);
        producerStatus.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        producerProgress = new JProgressBar(0, 100);
        producerProgress.setStringPainted(true);
        producerStatusPanel.add(producerStatus, BorderLayout.NORTH);
        producerStatusPanel.add(producerProgress, BorderLayout.CENTER);

        // 缓冲区状态面板
        JPanel bufferPanel = new JPanel(new BorderLayout());
        JLabel bufferStatus = new JLabel("缓冲区：空", SwingConstants.CENTER);
        bufferStatus.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        bufferPanel.add(bufferStatus, BorderLayout.CENTER);

        // 消费者状态面板
        JPanel consumerStatusPanel = new JPanel(new BorderLayout());
        JLabel consumerStatus = new JLabel("消费者：停止", SwingConstants.CENTER);
        consumerStatus.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        consumerProgress = new JProgressBar(0, 100);
        consumerProgress.setStringPainted(true);
        consumerStatusPanel.add(consumerStatus, BorderLayout.NORTH);
        consumerStatusPanel.add(consumerProgress, BorderLayout.CENTER);

        statusPanel.add(producerStatusPanel);
        statusPanel.add(bufferPanel);
        statusPanel.add(consumerStatusPanel);

        // 控制面板
        JPanel controlPanel = new JPanel();
        controlPanel.setLayout(new GridLayout(1, 4, 10, 10));
        controlPanel.setBackground(new Color(240, 240, 240));

        JButton startProducerButton = new JButton("开始生产");
        JButton stopProducerButton = new JButton("停止生产");
        JButton startConsumerButton = new JButton("开始消费");
        JButton stopConsumerButton = new JButton("停止消费");

        Font buttonFont = new Font("微软雅黑", Font.BOLD, 14);
        startProducerButton.setFont(buttonFont);
        stopProducerButton.setFont(buttonFont);
        startConsumerButton.setFont(buttonFont);
        stopConsumerButton.setFont(buttonFont);

        setupButtonStyle(startProducerButton, new Color(85, 200, 85));
        setupButtonStyle(stopProducerButton, new Color(255, 85, 85));
        setupButtonStyle(startConsumerButton, new Color(85, 85, 255));
        setupButtonStyle(stopConsumerButton, new Color(255, 165, 0));

        controlPanel.add(startProducerButton);
        controlPanel.add(stopProducerButton);
        controlPanel.add(startConsumerButton);
        controlPanel.add(stopConsumerButton);

        // 创建并启动线程
        Thread producer = new Thread(new Producer(labels, producerStatus, bufferStatus, producerProgress));
        producer.setDaemon(true);
        producer.start();

        Thread consumer = new Thread(new Consumer(labels, consumerStatus, bufferStatus, consumerProgress));
        consumer.setDaemon(true);
        consumer.start();

        // 按钮事件处理
        startProducerButton.addActionListener(e -> {
            synchronized (lock) {
                isProducing = true;
                producerStatus.setText("生产者：生产中");
                lock.notifyAll();
            }
        });

        stopProducerButton.addActionListener(e -> {
            synchronized (lock) {
                isProducing = false;
                producerStatus.setText("生产者：停止");
                lock.notifyAll();
            }
        });

        startConsumerButton.addActionListener(e -> {
            synchronized (lock) {
                isConsuming = true;
                consumerStatus.setText("消费者：消费中");
                lock.notifyAll();
            }
        });

        stopConsumerButton.addActionListener(e -> {
            synchronized (lock) {
                isConsuming = false;
                consumerStatus.setText("消费者：停止");
                lock.notifyAll();
            }
        });

        frame.add(panel, BorderLayout.CENTER);
        frame.add(statusPanel, BorderLayout.SOUTH);
        frame.add(controlPanel, BorderLayout.NORTH);
        frame.setVisible(true);
    }

    private static void setupButtonStyle(JButton button, Color bgColor) {
        button.setBackground(bgColor);
        button.setForeground(Color.WHITE);
        button.setFocusPainted(false);
        button.setFont(new Font("微软雅黑", Font.BOLD, 14));
        button.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                button.setBackground(bgColor.brighter());
            }

            public void mouseExited(java.awt.event.MouseEvent evt) {
                button.setBackground(bgColor);
            }
        });
    }

    private static void updateBufferStatus(JLabel bufferStatusLabel) {
        SwingUtilities.invokeLater(() -> {
            int size = buffer.size();
            if (size == 0) {
                bufferStatusLabel.setText("缓冲区：空");
                bufferStatusLabel.setForeground(Color.ORANGE);
            } else if (size == BUFFER_SIZE) {
                bufferStatusLabel.setText("缓冲区：满");
                bufferStatusLabel.setForeground(Color.RED);
            } else {
                bufferStatusLabel.setText("缓冲区：" + size + "/" + BUFFER_SIZE);
                bufferStatusLabel.setForeground(Color.BLACK);
            }
        });
    }

    static class Producer implements Runnable {
        private final JLabel[] labels;
        private final JLabel producerStatus;
        private final JLabel bufferStatus;
        private final JProgressBar producerProgress;

        public Producer(JLabel[] labels, JLabel producerStatus, JLabel bufferStatus, JProgressBar producerProgress) {
            this.labels = labels;
            this.producerStatus = producerStatus;
            this.bufferStatus = bufferStatus;
            this.producerProgress = producerProgress;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(10); // 主循环间隔缩短以快速响应停止
                    if (isProducing) {
                        synchronized (lock) {
                            while (buffer.size() == BUFFER_SIZE) {
                                SwingUtilities.invokeLater(() -> producerStatus.setText("生产者：等待（缓冲区满）"));
                                lock.wait();
                            }
                            if (!isProducing) continue;

                            // 生产单个产品
                            for (int progress = 0; progress <= 100; progress += 5) {
                                if (!isProducing) break;
                                final int p = progress;
                                SwingUtilities.invokeLater(() -> producerProgress.setValue(p));
                                Thread.sleep(50); // 总生产时间约1秒
                            }

                            if (!isProducing) {
                                SwingUtilities.invokeLater(() -> producerProgress.setValue(0));
                                continue;
                            }

                            buffer.add(1);
                            updateBuffer();
                            SwingUtilities.invokeLater(() -> producerProgress.setValue(0));
                            lock.notifyAll();
                        }
                    } else {
                        SwingUtilities.invokeLater(() -> producerProgress.setValue(0));
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void updateBuffer() {
            SwingUtilities.invokeLater(() -> {
                for (int i = 0; i < BUFFER_SIZE; i++) {
                    if (i < buffer.size()) {
                        labels[i].setText("产品");
                        labels[i].setBackground(Color.GREEN);
                    } else {
                        labels[i].setText("空");
                        labels[i].setBackground(Color.WHITE);
                    }
                }
                updateBufferStatus(bufferStatus);
            });
        }
    }

    static class Consumer implements Runnable {
        private final JLabel[] labels;
        private final JLabel consumerStatus;
        private final JLabel bufferStatus;
        private final JProgressBar consumerProgress;

        public Consumer(JLabel[] labels, JLabel consumerStatus, JLabel bufferStatus, JProgressBar consumerProgress) {
            this.labels = labels;
            this.consumerStatus = consumerStatus;
            this.bufferStatus = bufferStatus;
            this.consumerProgress = consumerProgress;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(10); // 主循环间隔缩短以快速响应停止
                    if (isConsuming) {
                        synchronized (lock) {
                            while (buffer.isEmpty()) {
                                SwingUtilities.invokeLater(() -> consumerStatus.setText("消费者：等待（缓冲区空）"));
                                lock.wait();
                            }
                            if (!isConsuming) continue;

                            // 消费单个产品
                            for (int progress = 0; progress <= 100; progress += 5) {
                                if (!isConsuming) break;
                                final int p = progress;
                                SwingUtilities.invokeLater(() -> consumerProgress.setValue(p));
                                Thread.sleep(75); // 总消费时间约1.5秒
                            }

                            if (!isConsuming) {
                                SwingUtilities.invokeLater(() -> consumerProgress.setValue(0));
                                continue;
                            }

                            buffer.poll();
                            updateBuffer();
                            SwingUtilities.invokeLater(() -> consumerProgress.setValue(0));
                            lock.notifyAll();
                        }
                    } else {
                        SwingUtilities.invokeLater(() -> consumerProgress.setValue(0));
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void updateBuffer() {
            SwingUtilities.invokeLater(() -> {
                for (int i = 0; i < BUFFER_SIZE; i++) {
                    if (i < buffer.size()) {
                        labels[i].setText("产品");
                        labels[i].setBackground(Color.GREEN);
                    } else {
                        labels[i].setText("空");
                        labels[i].setBackground(Color.WHITE);
                    }
                }
                updateBufferStatus(bufferStatus);
            });
        }
    }
}